﻿using System.Drawing;
using System.IO;
using Accusoft.ImagXpressSdk;

namespace picomp
{
    internal class PicResizer
    {
        private const int MAX_IMAGE_FILESIZE = 256*1024;
        private const int IMAGE_HEIGHT = 1200;
        private const int IMAGE_WIDTH = 2000;

        public PicResizer()
        {
            MaxHeight = IMAGE_HEIGHT;
            MaxWidth = IMAGE_WIDTH;
        }

        public int MaxHeight { get; set; }
        public int MaxWidth { get; set; }

        private bool Shrink(ImageX image)
        {
            var newWidth = image.Width;
            var newHeight = image.Height;
            var canShrink = false;

            if (newWidth > MaxWidth)
            {
                var aspectRatio = (float) newWidth/MaxWidth;
                newHeight = (int) (image.Height/aspectRatio);
                newWidth = MaxWidth;
                canShrink = true;
            }

            if (newHeight > MaxHeight)
            {
                var aspectRatio = (float) newHeight/MaxHeight;
                newWidth = (int) (newWidth/aspectRatio);
                newHeight = MaxHeight;
                canShrink = true;
            }

            if (canShrink)
            {
                using (var processor = new Processor(Licenser.ImagXContext) {Image = image})
                {
                    processor.Resize(new Size(newWidth, newHeight), ResizeType.Quality);
                }
            }

            return canShrink;
        }

        private bool shouldCompress(ImageX image, Stream stream)
        {
            var pixels = image.Width*image.Height;
            var ratio = (pixels/stream.Length);
            // 1600x1200 picture should be less than 200KB
            return (ratio < 9.375);
        }

        private bool shouldReject(Stream stream)
        {
            return stream.Length == 855054;
        }

        public Stream ResizeImage(Stream data)
        {
            if (shouldReject(data)) 
                return null;

            data.Seek(0, SeekOrigin.Begin);
            var image = ImageX.FromStream(Licenser.ImagXContext, data);
            var didShrink = Shrink(image);

            return didShrink ||
                   (image.Compression != Compression.Jpeg) ||
                   ((image.Compression == Compression.Jpeg) && shouldCompress(image, data))
                ? CompressJpeg(image)
                : data;
        }

        private static Stream CompressJpeg(ImageX image)
        {
            var options = new SaveOptions {Format = ImageXFormat.Jpeg};
            options.Jpeg.Luminance = 24;
            options.Jpeg.Chrominance = 24;
            options.Jpeg.SubSampling = SubSampling.SubSampling411;

            var result = new MemoryStream();
            {
                if (image.IptcDataSet != null)
                    image.IptcDataSet.Clear();

                for (var i = 1; i < image.JpegCommentCount; i++)
                {
                    image.DeleteJpegComment(i);
                }

                image.SaveStream(result, options);
                image.Dispose();
                return result;
            }
        }
    }
}